#include "lockGuard.hpp"
#include "thread.hpp"
#include <vector>
#include <queue>
using namespace std;

static int default_threadNum = 10;
template <class T>
class threadPool
{
public:
    threadPool(int threadNum = default_threadNum)
        : _threadNum(threadNum)
    {
        pthread_mutex_init(&_mutex , nullptr);
        pthread_cond_init(&_cond , nullptr);
        for (int i = 0; i < _threadNum; i++)
        {
            _threads.push_back(new Thread(handlerTask, this));
        }
    }
    void push_task(const T &inTask)
    {
        lockGuard lockguard = new lockGuard(&_mutex);
        _task_queue.push(inTask);
        pthread_cond_signal(&_cond);
    }
    static void *handlerTask(void *args)
    {
        threadPool<T> *threadpool = static_cast<threadPool<T> *>(args);
        while (true)
        {
            {
                lockGuard* lockguard = new lockGuard(&threadpool->_mutex);
                while (threadpool->isEmpty()) // warning!
                {
                    threadpool->threadWait();
                }
                // 执行任务，执行完之后将任务从队列中移除
                T task = threadpool->taskPop();
                // 任务是临界资源，要对其进行保护
            }
            //task(); // 执行任务，要放在外边
        }
        return nullptr;
    }

public:
    bool isEmpty()
    {
        return _task_queue.empty();
    }
    void threadWait()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    T taskPop() // 返回执行的任务
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }

public:
    void startPool()
    {
        for (int i = 0; i < _threadNum; i++)
        {
            _threads[i]->start(); // 启动每一个线程
            cout << _threads[i]->threadName() << " are started........" << endl;
        }
    }
    void executeJoin()
    {
        for (int i = 0; i < _threadNum; i++)
        {
            _threads[i]->join();
        }
    }
    ~threadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (auto e : _threads)
            delete e;
    }

private:
    int _threadNum;
    vector<Thread *> _threads;
    queue<T> _task_queue;

    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
};